/*
 * servidor.cpp
 *
 *  Created on: 03/10/2011
 *      Author: guido
 */

#include "servidor.h"
#include "constantes.h"
#include <stdio.h>
#include <cstring>
#include <stdlib.h>

Servidor::Servidor(short unsigned int puerto, char* rutaUsuarios)
try :
		socket(puerto), usuarios(rutaUsuarios) {
	this->seguirAceptando = true;
}
catch (ArchivoVacioException& ex) {
	throw;
}

Servidor::~Servidor() {

}

int Servidor::start() {
	if (!archivoClientes.good()) {
		return ERROR_PARAMETROS;
	} else {
		threader.crearThread(new MetodoAceptarConexion(this));
		char caracter;
		do {
			std::cin >> caracter;
		} while (caracter != 'q');
		if (caracter == 'q') {
			this->seguirAceptando = false;
			this->shutdown();
		}
		//TODO esperar que los threads se cierren, para que
		//no cierre el archivo mientras se le graban datos
	}
	return 0;
}

int Servidor::endianOpuesto(int i) {
	int temp = (i << 24) & 0xFF000000;
	temp += (i << 8) & 0x00FF0000;
	temp += (i >> 8) & 0x0000FF00;
	temp += i >> 24 & 0x000000FF;
	return temp;
}

std::string Servidor::recibirString(Socket* socket) {

	char tamanyoSerial[WORD_SIZE];
	socket->recibir(tamanyoSerial, WORD_SIZE);
	int numero;
	memcpy(&numero, tamanyoSerial, WORD_SIZE);
	int tamanyo = endianOpuesto(numero);
	char* cadena = new char[tamanyo + 1];cadena
	[tamanyo] = 0;
	socket->recibir(cadena, tamanyo);
	std::string nombre(cadena);
	delete[] cadena;
	return nombre;

}

void Servidor::shutdown() {
	socket.cerrar();
}

void MetodoAceptarConexion::run() {
	while (servidor->seguirAceptando) {
		Socket* cliente = new Socket(servidor->socket.aceptar());
		if (cliente->valido()) {
			servidor->threader.crearThread(
					new MetodoReceiveSend(servidor, cliente));
		}
		servidor->threader.limpiarThreads();
	}
}

void MetodoReceiveSend::run() {
	std::string nombre = servidor->recibirString(socket);
	std::string clave = servidor->recibirString(socket);
	char codigo;
	if (servidor->usuarios.usuarioExiste(nombre, clave)) {
		codigo = OK;
	} else {
		codigo = ERROR_USUARIO_INEXISTENTE;
	}
	socket->enviar(&codigo, 1);
	if (codigo == OK) {
		socket->recibir(&codigo, 1);
		if (codigo == 2) {
			std::string nueva = servidor->recibirString(socket);
			servidor->usuarios.cambiarClave(nombre, clave, nueva);
			codigo = 0;
			socket->enviar(&codigo, 1);
		}
	}
	delete socket;
}

